#include "jstring.h"

namespace JXQ
{

template <typename T>
static JBasicString<char> _s_floatToString(T num, int decimals, const char *f)
{
    if( decimals <= 0 )
		return JBasicString<char>::number(J_SCT(int64_t, num), 10);

    JBasicString<char> format_str = "%." + JBasicString<char>::number(decimals) + f;
	return JBasicString<char>::sprintf(format_str, num);
}

JXQLIB_EXPORT JBasicString<char> __floatToString(float num, int decimals, const char*)
{
	return _s_floatToString(num, decimals, "f");
}

JXQLIB_EXPORT JBasicString<char> __doubleToString(double num, int decimals, const char*)
{
	return _s_floatToString(num, decimals, "lf");
}

JXQLIB_EXPORT JBasicString<char> __LDoubleToString(long double num, int decimals, const char*)
{
	return _s_floatToString(num, decimals, "Lf");
}

template <typename T>
static JBasicString<wchar_t> _s_floatToString(T num, int decimals, const wchar_t *f)
{
    if( decimals <= 0 )
		return JBasicString<wchar_t>::number(J_SCT(int64_t, num), 10);

	JBasicString<wchar_t> format_str = L"%." + JBasicString<wchar_t>::number(decimals) + f;
	return JBasicString<wchar_t>::sprintf(format_str, num);
}

JXQLIB_EXPORT JBasicString<wchar_t> __floatToString(float num, int decimals, const wchar_t*)
{
	return _s_floatToString(num, decimals, L"f");
}

JXQLIB_EXPORT JBasicString<wchar_t> __doubleToString(double num, int decimals, const wchar_t*)
{
	return _s_floatToString(num, decimals, L"lf");
}

JXQLIB_EXPORT JBasicString<wchar_t> __LDoubleToString(long double num, int decimals, const wchar_t*)
{
	return _s_floatToString(num, decimals, L"Lf");
}

/*------------------------------------------------------------------------------------------------------------------------*/

template <typename T>
static inline int __jsscanf(const char *__restrict __s, const char *__restrict __format, T &buf)
{
#ifdef _MSC_VER
return sscanf_s(__s, __format, buf);
#else
return sscanf(__s, __format, &buf);
#endif
}

template <typename T>
static inline int __jsscanf(const wchar_t *__restrict __s, const wchar_t *__restrict __format, T &buf)
{
#ifdef _MSC_VER
return swscanf_s(__s, __format, buf);
#else
return swscanf(__s, __format, &buf);
#endif
}

template <typename T, typename TChar>
static T __stringToFloat(const JBasicString<TChar> &str, int decimals, const TChar *format)
{
    if( decimals < 0 )
		return T();

    size_t size = str.size();
    TChar *tmpStr = new TChar[size + 1];
    size_t index = 0;

    for(; index<size; index++)
    {
        tmpStr[index] = str[index];
        if( tmpStr[index] == '.' )
            break;
    }

    if( index + decimals + 1 < size )
        size = index + decimals + 1;

    for(; index<size; index++)
        tmpStr[index] = str[index];

    T tmp;
    __jsscanf(tmpStr, format, tmp);

    delete[] tmpStr;
	return tmp;
}

JXQLIB_EXPORT float __stringToFloat(const JBasicString<char> &str, int decimals)
{
    return __stringToFloat<float>(str, decimals, "%f");
}

JXQLIB_EXPORT double __stringToDouble(const JBasicString<char> &str, int decimals)
{
    return __stringToFloat<double>(str, decimals, "%lf");
}

JXQLIB_EXPORT long double __stringToLDouble(const JBasicString<char> &str, int decimals)
{
    return __stringToFloat<long double>(str, decimals, "%Lf");
}

JXQLIB_EXPORT float __stringToFloat(const JBasicString<wchar_t> &str, int decimals)
{
    return __stringToFloat<float>(str, decimals, L"%f");
}

JXQLIB_EXPORT double __stringToDouble(const JBasicString<wchar_t> &str, int decimals)
{
    return __stringToFloat<double>(str, decimals, L"%lf");
}

JXQLIB_EXPORT long double __stringToLDouble(const JBasicString<wchar_t> &str, int decimals)
{
    return __stringToFloat<long double>(str, decimals, L"%Lf");
}

} //namespace JXQ
